package com.zc.controller;


import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zc.common.Result;
import com.zc.exception.CustomerException;
import com.zc.pojo.Admin;
import com.zc.service.AdminService;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/admin")
public class AdminController {

    @Resource
    private AdminService adminService;


    @GetMapping("/page")
    public Result selectAll(@RequestParam(defaultValue = "1") Integer pageNum,
                            @RequestParam(defaultValue = "10") Integer pageSize,
                            Admin admin) {
        Page<Admin> adminPage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Admin> lqw = new LambdaQueryWrapper<>();
        lqw.orderByDesc(Admin::getId);
        // 非空判断（避免admin为null）
        if (admin != null) {
            // 用于标记是否已经添加过查询条件
            boolean hasCondition = false;

            // 姓名不为空时，添加姓名模糊查询
            if (StringUtils.hasText(admin.getName())) {
                lqw.like(Admin::getName, admin.getName());
                hasCondition = true;
            }

            // 用户名不为空时，添加用户名模糊查询（用OR连接）
            if (StringUtils.hasText(admin.getUsername())) {
                // 如果已有其他条件，则用OR连接；否则直接添加条件
                if (hasCondition) {
                    lqw.or().like(Admin::getUsername, admin.getUsername());
                } else {
                    lqw.like(Admin::getUsername, admin.getUsername());
                }
            }
        }
        return Result.success(adminService.page(adminPage, lqw));
    }

    @GetMapping("/{id}")
    public Result selectById(@PathVariable Integer id) {
        return Result.success(adminService.getById(id));
    }


    @PostMapping("/add")
    public Result save(@RequestBody Admin admin) {
        Admin one = adminService.getOne(new QueryWrapper<Admin>().eq("username", admin.getUsername()));
        if (one != null) {
            throw new CustomerException("账号重复");
        }
        if (StrUtil.isBlank(admin.getPassword())) {
            admin.setPassword("123");
        }
        admin.setRole("USER");
        //admin.setRole("ADMIN");
        return Result.success(adminService.save(admin));
    }

    @PutMapping("/update")
    public Result updateById(@RequestBody Admin admin) {
        Admin one = adminService.getOne(new QueryWrapper<Admin>().eq("username", admin.getUsername()));
        if (one == null) {
            throw new CustomerException("用户不存在");
        } else if (!one.getUsername().equals(admin.getUsername())) {
            throw new CustomerException("账号无法修改");
        }
        admin.setUpdateTime(new Date());
        return Result.success(adminService.updateById(admin));
    }


    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Integer id) {
        return Result.success(adminService.removeById(id));
    }

    @PostMapping("/deleteBatch") // 建议改为POST方法
    public Result deleteBatch(@RequestBody List<Integer> ids) { // 只接收ID列表
        // 增加参数校验
        if (ids == null || ids.isEmpty()) {
            return Result.error("请选择要删除的数据");
        }
        boolean success = adminService.removeBatchByIds(ids);
        return success ? Result.success("删除成功") : Result.error("删除失败");
    }

    //数据导出
    @GetMapping("/export")
    public void exportData(Admin admin,
                           @RequestParam(required = false) String ids,
                           HttpServletResponse response) throws Exception {
        // 1.拿取需要数据
        LambdaQueryWrapper<Admin> lmq = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(ids)) {
            List<Integer> idList = Arrays.stream(ids.split(","))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
            lmq.in(Admin::getId, idList);  // 按ID列表筛选
        } else if (StringUtils.hasText(admin.getUsername())) {
            lmq.like(Admin::getUsername, admin.getUsername());
        }
        List<Admin> adminList = adminService.list(lmq);
        // 2.构建Writer对象
        ExcelWriter writer = ExcelUtil.getWriter(true);
        // 3.设置中文表头
        writer.addHeaderAlias("username", "账号");
        writer.addHeaderAlias("name", "名称");
        //默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 4.写出数据到writer
        writer.write(adminList);
        // 5.设置输出的文件的名称以及输出流的头信息
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("管理员信息", StandardCharsets.UTF_8);
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
        // 6.写出到输出流并关闭writer
        ServletOutputStream os = response.getOutputStream();
        writer.flush(os);
        writer.close();
        os.close();
    }

    // 数据导入
    @PostMapping("/import")
    @Transactional(rollbackFor = Exception.class)
    public Result importData(MultipartFile file) throws Exception {
        // 1. 构建Reader并读取数据
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        reader.addHeaderAlias("账号", "username");
        reader.addHeaderAlias("名称", "name");
        List<Admin> list = reader.readAll(Admin.class);

        // 2. 数据校验准备
        Set<String> tempUsernameSet = new HashSet<>(list.size());    // 检测导入数据内部重复
        List<String> allUsernames = new ArrayList<>(list.size());    // 收集所有用户名
        List<String> errorMessages = new ArrayList<>();              // 错误信息收集

        // 3. 遍历数据进行校验
        for (int i = 0; i < list.size(); i++) {
            Admin admin = list.get(i);
            String username = admin.getUsername();
            int excelRow = i + 2;  // Excel数据行号（首行为标题）

            // 3.1 校验用户名非空
            if (StrUtil.isBlank(username)) {
                errorMessages.add("第" + excelRow + "行：用户名为空");
                continue;
            }

            // 3.2 校验当前导入数据内部重复
            if (!tempUsernameSet.add(username)) {
                errorMessages.add("第" + excelRow + "行：用户名重复");
                continue;
            }

            allUsernames.add(username);
            admin.setPassword("admin");  // 设置默认密码
        }

        // 4. 数据库重复校验（批量查询）
        if (!allUsernames.isEmpty()) {
            List<String> existUsernames = adminService.getExistingUsernames(allUsernames);
            for (int i = 0; i < list.size(); i++) {
                Admin admin = list.get(i);
                if (admin.getUsername() != null && existUsernames.contains(admin.getUsername())) {
                    errorMessages.add("第" + (i + 2) + "行：用户名已存在");
                }
            }
        }

        // 5. 错误处理
        if (!errorMessages.isEmpty()) {
            return Result.error("导入失败" + errorMessages);
        }

        // 6. 分批插入（每500条一批）
        int batchSize = 500;
        for (int i = 0; i < list.size(); i += batchSize) {
            int toIndex = Math.min(i + batchSize, list.size());
            adminService.saveBatch(list.subList(i, toIndex));
        }

        return Result.success("导入成功，共导入" + list.size() + "条数据");
    }

}

